package service

import (
	"context"
	"math"
	"mygf2/internal/model/entity"
	"regexp"
	"strings"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/text/gregex"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
)

var (
	DouyinService = douyinService{}
)

type douyinService struct{}
type DouyinUri struct {
	Uri     string   `json:"uri"`
	UrlList []string `json:"url_list"`
}
type DouyinVedio struct {
	PlayAddr     DouyinUri `json:"play_addr"`
	OriginCover  DouyinUri `json:"origin_cover"`
	DynamicCover DouyinUri `json:"dynamic_cover"`
	Cover        DouyinUri `json:"cover"`
	Vid          string    `json:"vid"`
	Height       int       `json:"height"`
	Width        int       `json:"width"`
	Ratio        string    `json:"ratio"`
	Duration     int       `json:"duration"`
	HasWatermark bool      `json:"has_watermark"`
}
type DouyinMusic struct {
	PlayUrl  DouyinUri `json:"play_url"`
	Title    string    `json:"title"`
	Duration int       `json:"duration"`
	Status   string    `json:"status"`
}
type DouyinItem struct {
	AwemeId    string                 `json:"aweme_id"`
	AwemeType  int                    `json:"aweme_type"`
	Video      DouyinVedio            `json:"video"`
	Music      DouyinMusic            `json:"music"`
	Author     map[string]interface{} `json:"author"`
	AnchorInfo map[string]interface{} `json:"anchor_info"`
	ShareInfo  map[string]string      `json:"share_info"`
	Desc       string                 `json:"desc"`
}

//某一视频信息得结构体
type DouyinRes struct {
	Extra      map[string]interface{} `json:"extra"`
	StatusCode *int                   `json:"status_code"`
	StatusMsg  string                 `json:"status_msg"`
	ItemList   []DouyinItem           `json:"item_list"`
	FilterList []interface{}          `json:"filter_list"`
}

//某一用户所有视频的结构体
type DouyinAuthorvideoRes struct {
	HasMore    bool                   `json:"has_more"`
	MaxCursor  int64                  `json:"max_cursor"`
	MinCursor  int64                  `json:"min_cursor"`
	Extra      map[string]interface{} `json:"extra"`
	StatusCode *int                   `json:"status_code"`
	StatusMsg  string                 `json:"status_msg"`
	AwemeList  []DouyinItem           `json:"aweme_list"`
}

func (d *douyinService) GetPrefixPattern() (res string) {
	res = `douyin\.com\/\w+`
	return
}
func (d *douyinService) MakeUrl(url string) (res string) {
	res = "https://v.douyin.com/" + url
	return
}
func (d *douyinService) GetTags(title string) string {
	//解析出tags
	title = strings.Trim(title, "#")
	tagList := strings.Split(title, "#")
	//fmt.Println(tagList)
	tags := []string{}

	for i := 1; i < len(tagList); i++ {
		tags = append(tags, gstr.TrimAll(tagList[i], SpecialCharacterMask...))
	}
	return strings.Join(tags, ",")
}
func (d *douyinService) FormatTitle(title string) string {
	//去掉@后的数据
	strList := strings.Split(title, "@")
	//fmt.Println(strList)
	return strings.TrimSpace(strList[0])
}
func (d *douyinService) GatherByAuthor(ctx context.Context, url string) (res []*entity.GatherUrls) {

	urlPatern := `www\.douyin\.com\/user\/([\w\/\-]*)`
	//fmt.Println(gregex.IsMatchString(urlPatern, url))
	userID := ""
	if gregex.IsMatchString(urlPatern, url) {
		//这里是pc端的主页地址
		urlMatchs, err := gregex.MatchString(urlPatern, url)
		if err != nil {
			return
		}
		if len(urlMatchs) < 2 {
			return
		}

		userID = urlMatchs[1]
	} else {
		//判断匹配嘛
		url = d.GetUrl(url)
		if url == "" {
			return
		}
		//fmt.Println(url)
		//fmt.Println("url", url)
		//请求短连接，获取真实地址
		r, e := g.Client().SetHeader("user-agent", UserAgent).Get(ctx, url)
		if e != nil {
			return
		}
		defer r.Close()
		fullUrl := r.Request.URL.String()
		//https://www.iesdouyin.com/share/user/MS4wLjABAAAA0wtQl1-U8s09knMfwhHc58QKOp2R5ozyxEGK0OPfUlU?
		// with_sec_did=1&
		// sec_uid=MS4wLjABAAAA0wtQl1-U8s09knMfwhHc58QKOp2R5ozyxEGK0OPfUlU&
		// u_code=22lafkfcg34l&
		// did=MS4wLjABAAAAItqrFiudtx7AHlfPk4JfkUvoUnpd12NjFC4FjKhifv8dn7PSmrf5gRbYusUgq866&
		// iid=MS4wLjABAAAARf9na6-iKkZOWZmBNvDpa_dMy7j0GvLMHU7MxiElugyj45Ky5dq9772BdId9sKuN&
		// timestamp=1647848622&
		// utm_source=copy&
		// utm_campaign=client_share&
		// utm_medium=android&
		// app=aweme
		//g.Log().Debug(ctx, fullUrl)
		//https://www.amemv.com/web/api/v2/aweme/post/?user_id=".$user_id."&sec_uid=&count=21&max_cursor=0&aid=1128
		pattern := `share/user/(.*)\?`
		reg := regexp.MustCompile(pattern)
		matchs := reg.FindAllStringSubmatch(fullUrl, -1)
		if matchs == nil {
			return
		}
		if len(matchs[0]) <= 1 {
			return
		}
		//用户id
		//组装接口地址
		userID = matchs[0][1]
	}
	var max_cursor int64 = 0
	for {
		userVideoUrl := "https://www.amemv.com/web/api/v2/aweme/post/?sec_uid=" + userID + "&max_cursor=" + gconv.String(max_cursor) + "&count=20"
		var authorVideoRes = new(DouyinAuthorvideoRes)
		g.Client().SetHeader("user-agent", UserAgent).GetVar(ctx, userVideoUrl).Scan(&authorVideoRes)
		if len(authorVideoRes.AwemeList) > 0 {
			//处理数据
			//fmt.Println(douyinRes)
			for _, item := range authorVideoRes.AwemeList {
				//不是视频
				if item.AwemeType != 4 {
					continue
				}
				//没有视频地址
				if item.Video.Vid == "" {
					continue
				}
				if len(item.Video.PlayAddr.UrlList) == 0 {
					continue
				}
				link := item.Video.PlayAddr.UrlList[0]
				queryData := new(entity.GatherUrls)
				queryData.Source = "douyin"
				queryData.Title = d.FormatTitle(item.Desc)
				queryData.Url = "https://www.douyin.com/video/" + item.AwemeId
				//获取宽高视频时长等
				queryData.Width = item.Video.Width
				queryData.OriginId = item.AwemeId
				queryData.Height = item.Video.Height
				duration := gconv.Float64(item.Video.Duration) / 1000.0
				queryData.Duration = gconv.Int(math.Ceil(duration))
				if len(item.Video.Cover.UrlList) > 0 {
					queryData.Cover = item.Video.Cover.UrlList[0]
				}
				queryData.NowatermarkUrl = strings.Replace(link, "playwm", "play", 1)
				queryData.Tags = d.GetTags(queryData.Title)
				//下一步进行存储数据库吧
				tbRes := GatherUrls().GatherInTable(ctx, queryData)
				if tbRes != nil {
					res = append(res, tbRes)
				}
			}
		}
		if !authorVideoRes.HasMore {
			//没有更多了
			break
		}
		max_cursor = authorVideoRes.MaxCursor
	}

	return
}
func (d *douyinService) Fetch(ctx context.Context, url string, taskChan chan interface{}) (res *entity.GatherUrls) {
	defer func() {
		taskChan <- res
	}()
	//判断匹配嘛
	url = d.GetUrl(url)
	if url == "" {
		return
	}
	//fmt.Println(url)
	//fmt.Println("url", url)
	//请求短连接，获取真实地址
	r, e := g.Client().SetHeader("user-agent", UserAgent).Get(ctx, url)
	if e != nil {
		return
	}
	defer r.Close()
	fullUrl := r.Request.URL.String()
	//fmt.Println("fullUrl", fullUrl)
	//匹配出视频id
	pattern := `video/\d+`
	reg := regexp.MustCompile(pattern)
	matchs := reg.FindAllString(fullUrl, -1)
	if matchs == nil {
		return
	}
	//视频id
	item_id := strings.Replace(matchs[0], "video/", "", -1)
	//组装视频长链接
	infourl := "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=" + item_id
	//fmt.Println("infourl", infourl)
	var douyinRes = new(DouyinRes)
	g.Client().SetHeader("user-agent", UserAgent).GetVar(ctx, infourl).Scan(&douyinRes)
	//没有值
	if len(douyinRes.ItemList) == 0 {
		return
	}
	//fmt.Println(douyinRes)
	item := douyinRes.ItemList[0]
	//不是视频
	if item.AwemeType != 4 {
		return
	}
	//没有视频地址
	if item.Video.Vid == "" {
		return
	}
	if len(item.Video.PlayAddr.UrlList) == 0 {
		return
	}
	link := item.Video.PlayAddr.UrlList[0]
	queryData := new(entity.GatherUrls)
	queryData.Source = "douyin"
	queryData.Title = d.FormatTitle(item.Desc)
	queryData.Url = "https://www.douyin.com/video/" + item_id
	//获取宽高视频时长等
	queryData.Width = item.Video.Width
	queryData.OriginId = item_id
	queryData.Height = item.Video.Height
	duration := gconv.Float64(item.Video.Duration) / 1000.0
	queryData.Duration = gconv.Int(math.Ceil(duration))
	if len(item.Video.Cover.UrlList) > 0 {
		queryData.Cover = item.Video.Cover.UrlList[0]
	}
	queryData.NowatermarkUrl = strings.Replace(link, "playwm", "play", 1)
	queryData.Tags = d.GetTags(queryData.Title)
	//下一步进行存储数据库吧
	res = GatherUrls().GatherInTable(ctx, queryData)
	return
}

func (d *douyinService) Download(ctx context.Context, url string) (res string, err error) {
	return
}
func (d *douyinService) GetUrl(url string) (res string) {
	pattern := d.GetPrefixPattern()
	reg := regexp.MustCompile(pattern)
	matchs := reg.FindAllString(url, -1)
	if matchs == nil {
		return ""
	}
	res = d.MakeUrl(strings.Replace(matchs[0], "douyin.com/", "", -1))
	return
}
